package cn.com.maven.designpattern.singleton;

import java.io.*;

/**
 * java 对象的序列化操作是实现Serializable接口，我们就可以把它往内存地写再从内存里读出而"组装"成一个跟原来一模一样的对象. 但是当我们遇到单例序列化
 * 的时候，就出现问题了。当从内存读出而组装的对象破坏了单例的规则，会创建新的对象。单例要求JVM只有一个对象，而通过反序化时就会产生一个克隆的对象，
 * 这就打破了单例的规则。
 * 而当实现了readResolve方法后，jvm就会有readResolve返回指定对象，也就保证了单例性。
 * 实验证明，如果没有声明readResolve方法，存入对象的hashcode和取出对象的hashcode不一致。
 * @Author YongQiang
 * @Date 2021/5/18 11:19
 * @Version 1.0
 */
public class SerializableSingleton implements Serializable {
    private static final long serialVersionUID = 3098263102708046641L;

    private static final SerializableSingleton instance = new SerializableSingleton();

    private SerializableSingleton(){

    }

    public static SerializableSingleton getInstance(){
        return instance;
    }

/*    protected Object readResolve(){
        System.out.println("调用了readResolve方法！");
        return instance;
    }*/

    public static void main(String[] args) {
        try {
            SerializableSingleton myObject = SerializableSingleton.getInstance();
            FileOutputStream fosRef = new FileOutputStream(new File(
                    "myObjectFile.txt"));
            ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
            oosRef.writeObject(myObject);
            oosRef.close();
            fosRef.close();
            System.out.println(myObject.hashCode());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            FileInputStream fisRef = new FileInputStream(new File(
                    "myObjectFile.txt"));
            ObjectInputStream iosRef = new ObjectInputStream(fisRef);
            SerializableSingleton myObject = (SerializableSingleton) iosRef.readObject();
            iosRef.close();
            fisRef.close();
            System.out.println(myObject.hashCode());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
